/*
 * I2C.c
 *
 *  Created on: 2013-4-6
 *      Author: Administrator
 */
#include"MSP430G2553.h"
#include"I2C.h"

#ifdef HARD_I2C		//Begin of Hard I2C

#define TX_STATE 						0					/*I2C״̬*/
#define RX_STATE						1					/*I2C״̬*/
//-----SMCLKƵI2CͨŲ-----
#define I2C_BAUDRATE_DIV 	30				/*I2Cʿ*/
#define SLAVE_ADDR 				0x20				/*ӻTCA6416Aĵַ*/
static unsigned char  TxByteCnt=0;				//ʣ෢
static unsigned char  RxByteCnt=0;				//ʣ
static unsigned char *pTxData;                     // TX ݵָ
static unsigned char *pRxData;                     // Rxմݵָ
unsigned char I2C_State =  0;						//շ״ָ̬ʾ
/******************************************************************************************************
 *        ƣI2C_Init()
 *        ܣʼUSCI_B0ģΪI2Cģʽ
 * ڲ
 * ڲ
 * ˵       I2CΪ3״̬ݲʹTxRxж
 *        
 ******************************************************************************************************/
void I2C_Init()
{
	 _disable_interrupts();
	  P1SEL |= BIT6 + BIT7;                      						// GPIO ΪUSCI_B0
	  P1SEL2|= BIT6 + BIT7;                    						 // GPIO ΪUSCI_B0
	  UCB0CTL1 |= UCSWRST;                      					 // λ״̬
	  UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;   // ͬͨI2C״̬
	  UCB0CTL1 = UCSSEL_2 + UCSWRST;            		 // ʹSMCLKλ״̬
	  UCB0BR0 =I2C_BAUDRATE_DIV ;                          // ˷ƵϵʵʲʻSMCLKй
	  UCB0BR1 = 0;														//һķƵһ㲻
	  UCB0I2CSA = SLAVE_ADDR;                    			// I2Cӻַں궨޸
	  UCB0CTL1 &= ~UCSWRST;                     				// I2C
	  _enable_interrupts();
}
/******************************************************************************************************
 *        ƣI2C_Tx_Init()
 *        ܣʹI2CTxж
 * ڲ
 * ڲ
 * ˵       I2Cֻͨܰ˫ֻʹһжϣɿ
 *        
 ******************************************************************************************************/
void I2C_Tx_Init()
{
	  _disable_interrupts();
	  while ((UCB0STAT & UCBUSY)||UCB0CTL1 & UCTXSTP);       // ȷ߿
	  IE2 &= ~UCB0RXIE;							//رRxж
	  I2C_State=TX_STATE;
	  IE2 |= UCB0TXIE;                          	    //Txж
	  _enable_interrupts();						// ж
}
/******************************************************************************************************
 *        ƣI2C_Rx_Init()
 *        ܣʹI2CRxж
 * ڲ
 * ڲ
 * ˵       I2Cֻͨܰ˫ֻʹһжϣɿ
 *        
 ******************************************************************************************************/
void I2C_Rx_Init()
{
	 _disable_interrupts();
	  while ((UCB0STAT & UCBUSY)||UCB0CTL1 & UCTXSTP);       // ȷ߿
	  IE2 &= ~UCB0TXIE;							//رRxж
	  I2C_State=RX_STATE;
	  IE2 |= UCB0RXIE;                          	    //Txж
	  _enable_interrupts();						// ж
}
/******************************************************************************************************
 *        ƣI2C_TxFrame()
 *        ܣ·1֡
 * ڲ*p_Tx ݵ׵ַ
 * 					   num ݵĸ
 * ڲ
 * ˵       ֻвBUSYSTOPѸλ²µ֡
 *        
 ******************************************************************************************************/
unsigned char I2C_TxFrame(unsigned char *p_Tx,unsigned char num)
{
	if ((UCB0STAT & UCBUSY)||(UCB0CTL1 & UCTXSTP))		return(0);
 	pTxData = (unsigned char *)p_Tx;     	// ָ
    TxByteCnt = num;                  					// ʣ෢ݸ
    UCB0CTL1 |= UCTR + UCTXSTT;            // I2C Txλ, start condition
    _bis_SR_register(CPUOFF+GIE);       		// LPM0ģʽж
    return(1);
}
/******************************************************************************************************
 *        ƣI2C_RxFrame()
 *        ܣ½1֡
 * ڲ*p_Tx ݴŵ׵ַ
 * 					   num ݵĸ
 * ˵       ֻвBUSYSTOPѸλ²µ֡
 *        
 ******************************************************************************************************/
unsigned char I2C_RxFrame(unsigned char *p_Rx,unsigned char num)
{
	if ((UCB0STAT & UCBUSY)||(UCB0CTL1 & UCTXSTP))		return(0);
	pRxData = (unsigned char *)p_Rx;     	// ָ
	 RxByteCnt= num;                  				// ʣݸ
	 UCB0CTL1 &= ~UCTR;
     UCB0CTL1 |= UCTXSTT;                    		// I2C Rxλ, start condition
    _bis_SR_register(CPUOFF+GIE);       	    //  LPM0ģʽж
    return(1);
 }
void I2C_TxFrame_ISR(void);
void I2C_RxFrame_ISR(void);
/******************************************************************************************************
 *        ƣUSCIAB0TX_ISR()
 *        ܣӦI2CշжϷ
 * ڲ
 * ڲ
 * ˵       I2CTxRxж
 *        
 ******************************************************************************************************/
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
	 _disable_interrupts();							//ͬ_DINT
  if(I2C_State==TX_STATE)							//ж״̬Ƿ״̬
    I2C_TxFrame_ISR();                        			// ¼֡
  else
	I2C_RxFrame_ISR();                     			// ¼֡
  	//-------ԤѭлCPU;-------
  	  if(RxByteCnt == 0 || TxByteCnt == 0)	//ûдͻ
  	    __bic_SR_register_on_exit(CPUOFF);   // Exit LPM0
  	 _enable_interrupts();							//ͬ_ENIT
}
/******************************************************************************************************
 *        ƣI2C_TxFrame_ISR()
 *        ܣI2CTx¼ͻе
 * ڲ
 * ڲ
 * ˵       FIFOָѭ
 *        
 ******************************************************************************************************/
void I2C_TxFrame_ISR(void)
{
   if (TxByteCnt)                            			// Ƿ
  {
    UCB0TXBUF = *pTxData;                   // װ
    pTxData++;											//ָλ
    TxByteCnt--;                            			// ݸݼ
  }
  else														//ݷ
  {
    UCB0CTL1 |= UCTXSTP;                   	// ֹͣλ
    IFG2 &= ~UCB0TXIFG;                     	// ˹־λûдBufferMCUԶ
  }
}
/******************************************************************************************************
 *        ƣI2C_RxFrame_ISR()
 *        ܣI2CRx¼ȡUCB0RXBUFдָ
 * ڲ
 * ڲ
 * ˵       ƶFIFOָѭ
 *        
 ******************************************************************************************************/
void I2C_RxFrame_ISR(void)
{
	  if (RxByteCnt == 1)                       			// ֻʣ1ֽûʱʵѾRxBuffˣ
	      UCB0CTL1 |= UCTXSTP;                  		// ֹͣλ
	  RxByteCnt--;                              				// ֽݼ
	  *pRxData = UCB0RXBUF;                  		// 洢ѽյ
	  *pRxData++;												//ָλ
}
#endif			//End of Hard I2C


#ifdef SOFT_I2C		//Begin of Soft I2C
#define MCLK_FREQ			1000000						// ˴дʵʱƵ
//-----Ӳ죬I2CIOк궨-----
#define I2C_CLK_HIGH 			P1DIR &=~BIT6;
#define I2C_CLK_LOW 			P1DIR |= BIT6; P1OUT &=~BIT6
#define I2C_DATA_HIGH 		P1DIR &=~BIT7
#define I2C_DATA_LOW 		P1DIR |= BIT7; P1OUT &=~BIT7
#define I2C_DATA_IN			P1IN&BIT7
#define I2C_START 				Start()
#define I2C_STOP 				 	Stop()
//-----ӻַ궨
#define SLAVE_ADDR			0x20				//дʵʵĴӻַ
#define SLAVE_ADDR_W	 	SLAVE_ADDR<<1			//Զɣ޸
#define SLAVE_ADDR_R		(SLAVE_ADDR<<1)+1	//Զɣ޸

//-----ΪӲI2CдĿպ
void I2C_Tx_Init(){}
void I2C_Rx_Init(){}
/******************************************************************************************************
 *        ƣdelay_us()
 *        ܣusȷʱ
 * ڲ
 * ڲ
 * ˵       ʵʱֵCPUʱƵйأʹMCLK_FREQ궨ʵԶ
 * 					ͬI2C豸ٶȲһһ100kHz400kHzĹ淶ʱ
 * 					ӡ
 *        
 ******************************************************************************************************/
static void delay_us()
{
//	_delay_cycles(MCLK_FREQ/1000);				//1000usʱ
//	_delay_cycles(MCLK_FREQ/10000);			//100usʱ
//	_delay_cycles(MCLK_FREQ/100000);			//10usʱ
//	_delay_cycles(MCLK_FREQ/1000000);		//1usʱ
}
/******************************************************************************************************
 *        ƣStart()
 *        ܣģI2Cʼλ
 * ڲ
 * ڲ
 * ˵       
 *        
 ******************************************************************************************************/
void Start()
{
	I2C_DATA_HIGH;
	delay_us();
	I2C_CLK_HIGH;
	delay_us();
	I2C_DATA_LOW;
	delay_us();
	I2C_CLK_LOW;
	delay_us();
}
/******************************************************************************************************
 *        ƣStop()
 *        ܣģI2Cֹͣλ
 * ڲ
 * ڲ
 * ˵       
 *        
 ******************************************************************************************************/
void Stop()
{
	I2C_CLK_LOW;
	delay_us();
	I2C_DATA_LOW;
	delay_us();
	I2C_CLK_HIGH;
	delay_us();
	I2C_DATA_HIGH;
	delay_us();
}
/******************************************************************************************************
 *        ƣI2C_Init()
 *        ܣӲI2Cĸʽһʼ
 * ڲ
 * ڲ
 * ˵       
 *        
 ******************************************************************************************************/
void I2C_Init()
{
	P1DIR |= BIT6;  		//SCLܽΪ
	P1DIR &= ~BIT7;	 //SDAܽΪ
	I2C_CLK_LOW;
	I2C_STOP;
}
/******************************************************************************************************
 *        ƣSend_Char()
 *        ܣӻ1ֽ
 * ڲ
 * ڲ
 * ˵       8λ󣬴ӻһӦλ
 *        
 ******************************************************************************************************/
void Send_Char(unsigned char data)
{
	unsigned char i=0;
	for(i=0;i<8;i++)
	{
		if((data<<i)&BIT7)
			I2C_DATA_HIGH;
		else
			I2C_DATA_LOW;
		I2C_CLK_HIGH;
		delay_us();
		I2C_CLK_LOW ;
		delay_us();
	}
	//----1CLKմӻӦλж----
	I2C_CLK_HIGH  ;
	delay_us();
	I2C_CLK_LOW;
	delay_us();
}
/******************************************************************************************************
 *        ƣ Master_Ack()
 *        ܣĽӦ
 * ڲ
 * ڲ
 * ˵       ӻ8ֽݺҪ߷0Ӧźš֮ͷߡ
 *        
 ******************************************************************************************************/
void Master_Ack()
{
	I2C_DATA_LOW;	//ߣ0ź
	delay_us();
	I2C_CLK_HIGH;	//Ӧλ0
	delay_us();
	//-----ͷ-----
	I2C_CLK_LOW;
	delay_us();
	I2C_DATA_HIGH;
}
/******************************************************************************************************
 *        ƣGet_Char()
 *        ܣմӻ1ֽ
 * ڲ
 * ڲ
 * ˵       һλݺҪӦλ
 *        
 ******************************************************************************************************/
unsigned char Get_Char()
{
	unsigned char i=0;
	unsigned char Temp=0;
	I2C_DATA_HIGH;
	for(i=0;i<8;i++)
	{
		I2C_CLK_HIGH;
		delay_us();
		Temp=Temp<<1;
		if((I2C_DATA_IN )== BIT7)		//ոλ
			Temp |=BIT0;
		delay_us();
		I2C_CLK_LOW ;
		delay_us();
	}
	//-----Ӧλ-----
	Master_Ack();
	return(Temp);
}
/******************************************************************************************************
 *        ƣI2C_TxFrame(unsigned char *p_Tx,unsigned char num)
 *        ܣֽڵ1֡
 * ڲ
 * ڲ
 * ˵       
 *        
 ******************************************************************************************************/
unsigned char I2C_TxFrame(unsigned char *p_Tx,unsigned char num)
{
	_disable_interrupts();
	unsigned char i=0;
	 I2C_START;
	 Send_Char(SLAVE_ADDR_W);		//ȷַд־
	for(i=0;i<num;i++)						//Ȼη͸ֽ
	{
		Send_Char(*p_Tx);
		p_Tx++;
	}
	I2C_STOP;
	 _enable_interrupts();
	return 1;
}
/******************************************************************************************************
 *        ƣI2C_RxFrame(unsigned char *p_Tx,unsigned char num)
 *        ܣֽڵ1֡
 * ڲ
 * ڲ
 * ˵       
 *        
 ******************************************************************************************************/
unsigned char I2C_RxFrame(unsigned char *p_Tx,unsigned char num)
{
	unsigned char i=0;
	_disable_interrupts();;
	 I2C_START;
	 Send_Char(SLAVE_ADDR_R);		//ȷַͶ־
	for(i=0;i<num;i++)						//Ȼνոֽ
	{
		*p_Tx=Get_Char();
		p_Tx++;
	}
	I2C_STOP;
	 _enable_interrupts();
	return 1;
}
#endif		//End of Soft I2C



